package com.wx.gof.pattern.structural.proxy.dynamicproxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @ClassName JayJdkProxy
 * @Author wx
 * @Description 周杰伦动态代理-接口方式-jdk自带动态代理
 * @Date 2018-12-11-22:58
 */
public class JayJdkProxy implements InvocationHandler {
    /**
     * 目标对象-被代理对象
     */
    private Object target;

    public JayJdkProxy(Object target) {
        this.target = target;
    }


    public Object bind() {
        Class cls = target.getClass();
        /**
         * 1.loader-构建代理类的模板路径 并不一定要是目标类，你随便使用一个存在的类路径都行
         * 2.interfaces-要实现的代理类的接口列表,可以直接传入Class<?>[]，此处是直接获取目标对象的接口列表
         * 3.h-调用方法处理程序
         */
        return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
    }

    /**
     * @param proxy  代理对象
     * @param method 代理对象方法
     * @param args   代理方法参数
     * @methodName: invoke
     * @author: wx
     * @description: 处理代理实例上的方法调用
     * @date: 2018/12/11
     * @return: java.lang.Object
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获取当前动态代理的方法名
        String methodName = method.getName();
        switch (methodName) {
            case "sign":
                //环绕处理
                aroundAdvice();
                return null;
            case "work":
                //前置处理
                beforeMethod();
                method.invoke(this.target, args);
                //后置处理
                afterMethod();
                return null;
            case "sing":
                // 获取当前方法传入参数
                Class<?>[] methodParameterTypes = method.getParameterTypes();
                System.out.print("我会唱:");
                for (int i = 0; i < methodParameterTypes.length; i++) {
                    System.out.println(args[i] + ",");
                }
                System.out.println("粉丝狂欢");
                method.invoke(this.target, args);
                return null;
            default:
                return method.invoke(this.target, args);
        }
    }

    /**
     * @param
     * @methodName: aroundAdvice
     * @author: wx
     * @description: 坏绕通知
     * @date: 2018/12/11
     * @return: void
     */
    private void aroundAdvice() {
        System.out.println("方文山代替周杰伦签约合同");
    }

    /**
     * @param
     * @methodName: beforeMethod
     * @author: wx
     * @description: 前置通知-前置增强
     * @date: 2018/12/11
     * @return: void
     */
    private void beforeMethod() {
        System.out.println("调整状态");
    }

    /**
     * @param
     * @methodName: afterMethod
     * @author: wx
     * @description: 后置通知
     * @date: 2018/12/11
     * @return: void
     */
    private void afterMethod() {
        System.out.println("休息一会");
    }
}
